#include "simulationcontroldialog.h"

#include "../../core/utils/validatormanager.h"
#include "../mainwindow.h"
#include "../utils/documentmanager.h"
#include "../utils/reportbuilder.h"
#include "../utils/simulationrunner.h"

#include <guicommon.h>
#include <iconmanager.h>

#include <QtGui/QHBoxLayout>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QPushButton>
#include <QtGui/QValidator>
#include <QtGui/QVBoxLayout>

using namespace core;
using namespace gui;
using namespace swp;

SimulationControlDialog::SimulationControlDialog(
    const QSharedPointer<SwpSimulationCaseDocument>& document,
    wfnet::WfNet* net, int repetitions, int timeout,
        QWidget* parent) :
            QDialog(parent),
            m_document(document),
            m_repDocument(QSharedPointer<SwpReportDocument>(0)),
            m_okButton(0),
            m_cancelButton(0),
            m_viewReportButton(0),
            m_repsL(0),
            m_toutL(0),
            m_status(0),
            m_error(0),
            m_repsE(0),
            m_toutE(0),
            m_net(net)
{
    setModal(true);
    setWindowTitle(tr("Run simulation"));

    createLayout(repetitions, timeout);
    connectSlots();
}

SimulationControlDialog::~SimulationControlDialog()
{

}

void SimulationControlDialog::createLayout(int repetitions, int timeout)
{
    QVBoxLayout* mainLayout = new QVBoxLayout;
    QHBoxLayout* buttonsLayout = new QHBoxLayout;

    m_repsL = new QLabel(tr("Repetitions"));
    m_toutL = new QLabel(tr("Timeout"));

    m_repsE = new QLineEdit;
    m_repsE->setText(QString::number(repetitions));
    m_repsE->setValidator(
        ValidatorManager::getInstance()->getValidator(
            INT_PROPERTY_VALIDATOR).data());
    m_toutE = new QLineEdit;
    m_toutE->setText(QString::number(timeout));
    m_toutE->setValidator(
        ValidatorManager::getInstance()->getValidator(
            INT_PROPERTY_VALIDATOR).data());

    m_repsL->setBuddy(m_repsE);
    m_toutL->setBuddy(m_toutE);

    m_status = new QLabel();
    m_status->hide();

    m_error = new QLabel();
    m_error->hide();
    m_error->setStyleSheet("QLabel { color: red; }");

    mainLayout->addWidget(m_error);
    mainLayout->addWidget(m_repsL);
    mainLayout->addWidget(m_repsE);
    mainLayout->addWidget(m_toutL);
    mainLayout->addWidget(m_toutE);
    mainLayout->addWidget(m_status);

    IconManager* im = IconManager::getInstance();

    m_okButton = new QPushButton(tr("Simulate"));
    if (im->hasIcon("SwpRunSimulationDialog"))
    {
        m_okButton->setIcon(im->icon("SwpRunSimulationDialog"));
    }
    m_cancelButton = new QPushButton(tr("Cancel"));
    m_viewReportButton = new QPushButton(tr("View report"));
    if (im->hasIcon("SwpViewReportDialog"))
    {
        m_viewReportButton->setIcon(im->icon("SwpViewReportDialog"));
    }

    m_viewReportButton->hide();

    buttonsLayout->addWidget(m_okButton);
    buttonsLayout->addWidget(m_viewReportButton);
    buttonsLayout->addWidget(m_cancelButton);
    buttonsLayout->addStretch();

    mainLayout->addLayout(buttonsLayout);
    setLayout(mainLayout);

    connect(m_okButton, SIGNAL(clicked()),
        this, SLOT(accept()));
    connect(m_cancelButton, SIGNAL(clicked()),
        this, SLOT(reject()));
    connect(m_viewReportButton, SIGNAL(clicked()),
        this, SLOT(viewReport()));
}

void SimulationControlDialog::connectSlots()
{
    connect(SimulationRunner::getInstance(), SIGNAL(simulationFinished(bool)),
        this, SLOT(finished(bool)));
}

void SimulationControlDialog::showInputs()
{
    m_status->hide();

    m_repsL->show();
    m_toutL->show();

    m_repsE->show();
    m_toutE->show();
}

void SimulationControlDialog::hideInputs()
{
    m_repsL->hide();
    m_toutL->hide();

    m_repsE->hide();
    m_toutE->hide();

    m_status->show();
}

void SimulationControlDialog::accept()
{
    IconManager* im = IconManager::getInstance();

    m_status->setText(tr("Simulation in progres..."));
    m_error->hide();
    hideInputs();

    m_okButton->setText(tr("Stop"));
    if (im->hasIcon("SwpStopSimulationDialog"))
    {
        m_okButton->setIcon(im->icon("SwpStopSimulationDialog"));
    }
    m_cancelButton->setEnabled(false);
    m_viewReportButton->hide();

    disconnect(m_okButton, SIGNAL(clicked()),
            this, SLOT(accept()));
    connect(m_okButton, SIGNAL(clicked()),
            this, SLOT(stop()));

    SimulationRunner::getInstance()->simulate(m_net, m_repsE->text().toInt(),
        m_toutE->text().toInt());
}

void SimulationControlDialog::reject()
{
    m_document = QSharedPointer<SwpSimulationCaseDocument>(0);
    m_repDocument = QSharedPointer<SwpReportDocument>(0);

    QDialog::reject();
}

void SimulationControlDialog::finished(bool interrupted)
{   
    if (!interrupted)
    {
        m_status->setText(tr("Generating report..."));
        m_repDocument = ReportBuilder::getInstance()->build(m_document);
        m_repDocument->addLink(m_document);

        DocumentManager::getInstance()->addDocument(
            m_document->container(), m_repDocument, 0);
    }

    IconManager* im = IconManager::getInstance();

    if (interrupted)
    {
        m_error->setText(tr("Simulation was interrupted either by manual stop"
            " or timeout."));
        m_error->show();
    }
    showInputs();

    m_okButton->setText(tr("Simulate again"));
    if (im->hasIcon("SwpRunSimulationDialog"))
    {
        m_okButton->setIcon(im->icon("SwpRunSimulationDialog"));
    }
    m_cancelButton->setEnabled(true);

    disconnect(m_okButton, SIGNAL(clicked()),
            this, SLOT(stop()));
    connect(m_okButton, SIGNAL(clicked()),
            this, SLOT(accept()));

    if (!interrupted)
    {
        m_viewReportButton->show();
    }
}

void SimulationControlDialog::stop()
{
    SimulationRunner::getInstance()->stop();
}

void SimulationControlDialog::viewReport()
{
    Q_ASSERT(!m_repDocument.isNull());

    QDialog::done(QDialog::Accepted);

    DocumentManager::getInstance()->openDocument(m_repDocument);
    MainWindow::getInstance()->changePerspective(2);
}
